package com.mo.config.filter;

import com.mo.constant.Constants;
import com.mo.model.TUser;
import com.mo.result.CodeEnum;
import com.mo.result.R;
import com.mo.util.JSONUtils;
import com.mo.util.JWTUtils;
import com.mo.util.ResponseUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author mo
 * version
 */
@Component
public class TokenVerifyFilter extends OncePerRequestFilter {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (request.getRequestURI().equals(Constants.LOGIN_URI)){
            filterChain.doFilter(request,response);
        }
        String token = null;
        if (request.getRequestURI().equals(Constants.EXPORT_EXCEL_URI)){
            token =request.getParameter("Authorization");
        }else {
            token = request.getHeader("Authorization");
        }
        String rememberMe = request.getHeader("rememberMe"); // 提前获取rememberMe
            if (!StringUtils.hasText(token)) {
                R result = R.FAIL(CodeEnum.FAIL);
                String resultJson = JSONUtils.toJSON(result);
                ResponseUtils.write(response, resultJson);
                return;
            }

            //验证token有没有被篡改过
            if (!JWTUtils.verifyJWT(token)) {
                //token验证未通过统一结果
                R result = R.FAIL(CodeEnum.TOKEN_IS_ERROR);

                //把R对象转成json
                String resultJSON = JSONUtils.toJSON(result);

                //把R以json返回给前端
                ResponseUtils.write(response, resultJSON);

                return;
            }


            TUser tUser = JWTUtils.parseUserFromJWT(token);
            String redisToken = stringRedisTemplate.opsForValue().get(Constants.REDIS_JWT_KEY + tUser.getId());
            if (!StringUtils.hasText(redisToken)){
                R result = R.FAIL(CodeEnum.TOKEN_IS_EXPIRED);
                String resultJSON = JSONUtils.toJSON(result);
                ResponseUtils.write(response,resultJSON);
                return;
            }

            if (!token.equals(redisToken)){
                R result = R.FAIL(CodeEnum.TOKEN_IS_NONE_MATCH);
                String resultJSON = JSONUtils.toJSON(result);
                ResponseUtils.write(response,resultJSON);
                return;
            }
            //jwt验证通过了，那么在spring security的上下文环境中要设置一下，设置当前这个人是登录过的，你后续不要再拦截他了
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(tUser, tUser.getLoginPwd(), tUser.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);


//            new Thread(()->{
//                if (Boolean.parseBoolean(request.getParameter("rememberMe"))){
//                    redisService.expire(key,Constants.EXPIRE_TIME, TimeUnit.SECONDS);
//                }else {
//                    redisService.expire(key,Constants.DEFAULT_EXPIRE_TIME,TimeUnit.SECONDS);
//                }
//            }).start();
            //token续期

            threadPoolTaskExecutor.execute(()->{
                //刷新token
                if (Boolean.parseBoolean(rememberMe)) {
                    stringRedisTemplate.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.EXPIRE_TIME, TimeUnit.SECONDS);
                } else {
                    stringRedisTemplate.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS);
                }
            });
            //验证jwt通过了 ，让Filter链继续执行，也就是继续执行下一个Filter

            filterChain.doFilter(request, response);
        }
    }

